#include "app_main_view.h"

#include <M5EPD.h>
#include <WString.h>

// 字体路径，在SD卡上保存
#define TTF_FONT_PATH "/hei.ttf"

// 字体大小
static constexpr int APP_FONT_SIZE = 32;

// 缓存字体数量
static constexpr int APP_RENDER_CACHE = 256;

// 多行文本的行间距
static constexpr int FONT_LINE_DIFF = 48;

// 屏幕宽度、高度
static constexpr int EPD_DISPLAY_WIDTH = M5EPD_PANEL_W;   // 960
static constexpr int EPD_DISPLAY_HEIGHT = M5EPD_PANEL_H;  // 540

// 屏幕内容一共分为4列
static constexpr int APP_COLUMN_COUNT = 4;
static constexpr int APP_COLUMN_WIDTH = (EPD_DISPLAY_WIDTH / APP_COLUMN_COUNT);

// 底部区域高度
static constexpr int APP_FOOTER_HEIGHT = 4 * APP_FONT_SIZE;

static M5EPD_Canvas& GetCanvas() {
  static M5EPD_Canvas canvas(&M5.EPD);
  return canvas;
}

#define APP_CANVAS GetCanvas()

void AppMainView::UpdateSensorState(const AppSensorModel& state) {
  this->sensorState_ = state;
}

void AppMainView::UpdateLocationState(const AppLocationModel& location) {
  this->locationState_ = location;
}

void AppMainView::UpdateRealtimeWeather(const AppRealtimeWeather& weather) {
  this->realtimeWeather_ = weather;
}

void AppMainView::UpdateForecastWeather(const AppForecastWeather& weather) {
  this->forecastWeather_ = weather;
}

bool AppMainView::Initialize() {
  M5.TP.SetRotation(0);
  M5.EPD.SetRotation(0);
  M5.EPD.Clear(true);  // 清除屏幕

  APP_CANVAS.loadFont(TTF_FONT_PATH, SD);
  APP_CANVAS.createCanvas(EPD_DISPLAY_WIDTH, EPD_DISPLAY_HEIGHT);
  APP_CANVAS.createRender(APP_FONT_SIZE, APP_RENDER_CACHE);
  APP_CANVAS.setTextSize(APP_FONT_SIZE);

  yBaseLine_ = APP_FONT_SIZE / 2;
  return true;
}

void AppMainView::SetRtcDevice(HalRtcDevice* device) {
  this->rtcDevice_ = device;
}

void AppMainView::DrawMainView() {
  APP_CANVAS.clear();                 // 清屏
  APP_CANVAS.setTextDatum(TL_DATUM);  // 左上角

  DrawGridLayout();
  DrawSensorState();
  DrawLocationState();
  DrawDateTime();
  // DrawRealtimeWeather();
  DrawForecastWeather();

  DrawFooterText();

  APP_CANVAS.pushCanvas(0, 0, UPDATE_MODE_GL16);  // 刷屏
}

void AppMainView::DrawConfigLoadView() {
  APP_CANVAS.clear();                 // 清屏
  APP_CANVAS.setTextDatum(MC_DATUM);  // 居中

  SetCursor(EPD_DISPLAY_WIDTH / 2,
            EPD_DISPLAY_HEIGHT / 2 - FONT_LINE_DIFF * 1.5);
  DrawString("正在加载SD卡文件/config.json ...");
  yCursor_ += FONT_LINE_DIFF;

  DrawString("解析WiFi热点SSID、密码 ...");
  yCursor_ += FONT_LINE_DIFF;

  DrawString("解析高德云服务API KEY ...");

  APP_CANVAS.pushCanvas(0, 0, UPDATE_MODE_GL16);  // 刷屏
}

void AppMainView::DrawWifiConnectView() {
  APP_CANVAS.clear();                 // 清屏
  APP_CANVAS.setTextDatum(MC_DATUM);  // 居中

  SetCursor(EPD_DISPLAY_WIDTH / 2, EPD_DISPLAY_HEIGHT / 2);
  DrawString("正在连接WiFi热点 ...");

  APP_CANVAS.pushCanvas(0, 0, UPDATE_MODE_GL16);  // 刷屏
}

void AppMainView::DrawTimeRequestView() {
  APP_CANVAS.clear();                 // 清屏
  APP_CANVAS.setTextDatum(MC_DATUM);  // 居中

  SetCursor(EPD_DISPLAY_WIDTH / 2, EPD_DISPLAY_HEIGHT / 2);
  DrawString("正在获取网络时间 ...");

  APP_CANVAS.pushCanvas(0, 0, UPDATE_MODE_GL16);  // 刷屏
}

void AppMainView::DrawTimeUpdateView() {
  APP_CANVAS.clear();                 // 清屏
  APP_CANVAS.setTextDatum(MC_DATUM);  // 居中

  SetCursor(EPD_DISPLAY_WIDTH / 2, EPD_DISPLAY_HEIGHT / 2);
  DrawString("正在设置RTC时间 ...");

  APP_CANVAS.pushCanvas(0, 0, UPDATE_MODE_GL16);  // 刷屏
}

void AppMainView::DrawLocationRequestView() {
  APP_CANVAS.clear();                 // 清屏
  APP_CANVAS.setTextDatum(MC_DATUM);  // 居中

  SetCursor(EPD_DISPLAY_WIDTH / 2, EPD_DISPLAY_HEIGHT / 2 - FONT_LINE_DIFF);
  DrawString("正在查询公网IP地址 ...");
  yCursor_ += FONT_LINE_DIFF;

  DrawString("正在请求高德IP定位 ...");

  APP_CANVAS.pushCanvas(0, 0, UPDATE_MODE_GL16);  // 刷屏
}

void AppMainView::DrawWeatherRequestView() {
  APP_CANVAS.clear();                 // 清屏
  APP_CANVAS.setTextDatum(MC_DATUM);  // 居中

  SetCursor(EPD_DISPLAY_WIDTH / 2, EPD_DISPLAY_HEIGHT / 2 - FONT_LINE_DIFF);
  DrawString("正在请求高德实时天气 ...");
  yCursor_ += FONT_LINE_DIFF;

  DrawString("正在请求高德预报天气 ...");

  APP_CANVAS.pushCanvas(0, 0, UPDATE_MODE_GL16);  // 刷屏
}

void AppMainView::DrawGridLayout() {
  // 屏幕内容一共分为4列
  // 绘制三条垂直分割线：
  for (int i = 1; i < APP_COLUMN_COUNT; i++) {
    APP_CANVAS.drawFastVLine(i * APP_COLUMN_WIDTH, 0, EPD_DISPLAY_HEIGHT, 7);
  }

  // 绘制三个水平矩形区域
  // APP_CANVAS.drawFastHLine(0, EPD_DISPLAY_HEIGHT / 2, EPD_DISPLAY_WIDTH, 7);
  APP_CANVAS.fillRect(0, 0, EPD_DISPLAY_WIDTH, 2 * APP_FONT_SIZE, 11);

  APP_CANVAS.fillRect(0, EPD_DISPLAY_HEIGHT - APP_FOOTER_HEIGHT,
                      EPD_DISPLAY_WIDTH, APP_FOOTER_HEIGHT, 15);
}

void AppMainView::SetCursor(int x, int y) {
  xCursor_ = x;
  yCursor_ = y;
}

void AppMainView::DrawString(String str) {
  APP_CANVAS.drawString(str, xCursor_, yCursor_);
  Serial.printf("drawString(`%s`, %d, %d) done!\r\n", str.c_str(), xCursor_,
                yCursor_);
}

static String DateVal(String value) {
  int year = 0;
  int mon = 0;
  int day = 0;
  sscanf(value.c_str(), "%d-%02d-%02d", &year, &mon, &day);

  char buffer[64] = "";
  snprintf(buffer, sizeof(buffer), "%d-%02d-%02d", year, mon, day);
  return String(buffer);
}

static String Weather(String value) { return "天气：" + value; }
static String TempVal(String value) { return "温度：" + value + "℃"; }
static String HumiVal(String value) { return "湿度：" + value + "%"; }
static String WindDir(String value) { return "风向：" + value; }
static String WindPow(String value) { return "风力：" + value; }

void AppMainView::DrawSensorState() {
  int16_t count = 0;
  APP_CANVAS.setTextColor(0);

  SetCursor(0, yBaseLine_);

  DrawString(TempVal(String(sensorState_.temp, 2)));
  xCursor_ += APP_COLUMN_WIDTH;

  DrawString(HumiVal(String(sensorState_.humi, 2)));
  xCursor_ += APP_COLUMN_WIDTH;
}

void AppMainView::DrawLocationState() {
  APP_CANVAS.setTextColor(0);

  SetCursor(2 * APP_COLUMN_WIDTH, yBaseLine_);

  DrawString(locationState_.origin.province);
  xCursor_ += APP_COLUMN_WIDTH;

  DrawString(locationState_.origin.city);
  xCursor_ += APP_COLUMN_WIDTH;
}

void AppMainView::DrawDateTime() {
  char buffer[64];
  if (!rtcDevice_) {
    Serial.printf("rtcDevice_ invalid!\r\n");
    return;
  }

  APP_CANVAS.setTextDatum(TR_DATUM);  // 右上角计算
  APP_CANVAS.setTextColor(0);

#if 0
  HalRtcDevice::Date date;
  if (!rtcDevice_->GetDate(date)) {
    Serial.printf("DrawDateTime GetDate failed!\r\n");
    return;
  }

  snprintf(buffer, sizeof(buffer), "%d-%02d-%02d", date.year, date.mon,
           date.day);

  DrawString(buffer);
  yCursor_ += FONT_LINE_DIFF;
#endif

  HalRtcDevice::Time time;
  if (rtcDevice_->GetTime(time)) {
    snprintf(buffer, sizeof(buffer), "%02d:%02d ", time.hour, time.min);
    SetCursor(EPD_DISPLAY_WIDTH, yBaseLine_);
    DrawString(buffer);
  }

  APP_CANVAS.setTextDatum(TL_DATUM);  // 左上角
}

#if 0
void AppMainView::DrawRealtimeWeather() {
  DrawString(Weather(realtimeWeather_.weather));
  yCursor_ += FONT_LINE_DIFF;

  DrawString(TempVal(realtimeWeather_.temperature));
  yCursor_ += FONT_LINE_DIFF;

  DrawString(HumiVal(realtimeWeather_.humidity));
  yCursor_ += FONT_LINE_DIFF;

  DrawString(WindDir(realtimeWeather_.winddirection));
  yCursor_ += FONT_LINE_DIFF;

  DrawString(WindPow(realtimeWeather_.windpower));
  yCursor_ += FONT_LINE_DIFF;
}
#endif

void AppMainView::DrawForecastWeather() {
  APP_CANVAS.setTextColor(15);
  int yBase = 3.5 * APP_FONT_SIZE;
  SetCursor(0, yBase);
  for (int i = 0; i < webapi::AmapForecastWeather::kDays; i++) {
    yCursor_ = yBase;

    auto& cast = forecastWeather_.casts[i];
    DrawString(DateVal(cast.date));
    yCursor_ += FONT_LINE_DIFF;

    DrawString(Weather(cast.dayweather));
    yCursor_ += FONT_LINE_DIFF;

    DrawString(TempVal(cast.daytemp));
    yCursor_ += FONT_LINE_DIFF;

    DrawString(WindDir(cast.daywind));
    yCursor_ += FONT_LINE_DIFF;

    DrawString(WindPow(cast.daypower));
    yCursor_ += FONT_LINE_DIFF;

    xCursor_ += APP_COLUMN_WIDTH;
  }
}

void AppMainView::DrawFooterText() {
  APP_CANVAS.setTextDatum(MC_DATUM);  // 居中
  APP_CANVAS.setTextColor(0);
  SetCursor(EPD_DISPLAY_WIDTH / 2, EPD_DISPLAY_HEIGHT - APP_FONT_SIZE * 3);

  DrawString("【DigiKey“智造万物，快乐不停”创意大赛】");
  yCursor_ += FONT_LINE_DIFF;

  APP_CANVAS.setTextColor(3);
  DrawString("By xusiwei1236, with Arduino IDE.");
  yCursor_ += FONT_LINE_DIFF;
}
